package me.zhengjie.nettydemo.nettty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import me.zhengjie.nettydemo.lift.LiftStatusVo;
import me.zhengjie.nettydemo.mapper.LiftNettyMapper;
import me.zhengjie.sqlservilce.LiftSqlService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.net.SocketAddress;

/**
 * @author : huang
 * @since : 2024/5/9 9:25
 */

@Slf4j
public class SimpleClientHandler extends ChannelInboundHandlerAdapter {
    private static final Logger liftLog = LoggerFactory.getLogger("lift");

    private final LiftNettyMapper liftMapper;

    private final LiftSqlService liftSqlService;


    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        SocketAddress socketAddress = ctx.channel().remoteAddress();
        if (socketAddress != null) {
            if (socketAddress instanceof InetSocketAddress) {
                InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
                // 获取IP地址
                String ip = inetSocketAddress.getAddress().getHostAddress();
                // 获取端口号
                int port = inetSocketAddress.getPort();
                liftLog.info("连接断开: IP={}, 端口={}", ip, port);
                val lift = liftSqlService.selectIpPort(ip, port);
                String liftCode1 = lift.getLiftCode();
                LiftCenter.liftClientMap.remove(liftCode1);
                while (true) {
                    LiftClient client = new LiftClient(lift.getIp(), lift.getPort(), liftCode1,liftMapper, liftSqlService);
                    boolean connect = client.connect();
                    if (connect) {
                        liftLog.info("重连成功: IP={}, 端口={}", ip, port);
                        liftLog.info("查询liftClientMap中key参数:{},值：{}", LiftCenter.liftClientMap.keySet(), LiftCenter.liftClientMap.values());
                        // 更新liftClientMap中的引用
                        LiftCenter.liftClientMap.put("lift1", client);
                        liftLog.info("重连后liftClientMap中参数:{}", LiftCenter.liftClientMap);
                        break;
                    } else {
                        try {
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
                ;
            } else {
                liftLog.error("未知的SocketAddress类型: {}", socketAddress.getClass().getName());
            }
        } else {
            liftLog.error("重连失败，socketAddress为null");
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

    }

    private final String liftCode;

    public SimpleClientHandler(LiftNettyMapper liftMapper, LiftSqlService liftSqlService, String liftCode) {
        this.liftMapper = liftMapper;
        this.liftSqlService = liftSqlService;
        this.liftCode = liftCode;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        SocketAddress socketAddress = ctx.channel().remoteAddress();
        InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
        ByteBuf buf = (ByteBuf) msg;
        liftLog.info("响应接收：{},ip:{}", ByteBufUtil.hexDump(buf), inetSocketAddress.getAddress().getHostAddress());
        try {

            if (!buf.isReadable()) {
                liftLog.error("No more readable bytes after frame header");
                return;
            }
//            // 帧头
//            byte b = buf.readByte();
//            liftLog.info("响应接收，帧头为:{}", b);
//            if (b != (byte) 0x01) {
//                liftLog.error("响应接收异常，帧头不正确");
//                return;
//            }
            // 功能码
            if (!buf.isReadable()) {
                liftLog.error("No more readable bytes after function code");
                return;
            }
            byte b1 = buf.readByte();
            liftLog.info("功能码：{}", b1);
            // 写指令
            if (b1 == (byte) 0x06) {
                // 地址位
                if (!buf.isReadable()) {
                    liftLog.error("No more readable bytes after address byte");
                    return;
                }
                buf.readByte();
                byte b2 = buf.readByte();
                if (b2 == (byte) 0x56) {
                    // 门状态回复
                    if (!buf.isReadable()) {
                        liftLog.error("No more readable bytes after door status byte");
                        return;
                    }
                    buf.readByte();
                    byte door = buf.readByte();
                    if (door == (byte) 0x03) {
                        // 开门指令回复
                        liftLog.info("开门指令回复");
                        liftMapper.storage0penDoor(liftCode, 1);
                    } else if (door == (byte) 0x04) {
                        // 关门指令回复
                        liftLog.info("关门指令回复");
                        liftMapper.storageCloseDoorFrame(liftCode, 1);
                    }
                } else if (b2 == (byte) 0x99) {
                    // 呼叫电梯
                    liftMapper.storageCallLiftFrame(liftCode, 1);
                }
            } else if (b1 == (byte) 0x03) {
                // 长度
                if (!buf.isReadable()) {
                    liftLog.error("No more readable bytes after length byte");
                    return;
                }
                buf.readByte();
                buf.readByte();
                int liftStatus = buf.readByte();
                buf.readByte();
                int running = buf.readByte();
                buf.readByte();
                byte liftDoorStatus = buf.readByte();
                buf.readByte();
                buf.readByte();
                buf.readByte();
                byte currentFloor = buf.readByte();
                liftLog.info("添加电梯状态：{},{},{},{}", liftStatus, running, liftDoorStatus, currentFloor);
                LiftStatusVo liftStatusVo = new LiftStatusVo(liftStatus, running, liftDoorStatus, currentFloor);
                liftMapper.storageLiftStatusFrame(liftCode, liftStatusVo);
            }
        } finally {
            liftLog.info("释放");
            buf.clear();
            ReferenceCountUtil.release(buf);
        }
    }

//    private static LiftStatusVo liftInfoAnalyze(ByteBuf buf) {
//        byte answerTheOrder = buf.readByte();
//        if (answerTheOrder != (byte) 0xC0) {
//            liftLog.error("电梯信息查询，应答命令异常：{}", answerTheOrder);
//            return null;
//        }
//
//        byte answerDescription = buf.readByte();
//        if (answerDescription == (byte) 0x03) {
//            liftLog.error("电梯信息查询，应答描述异常：{}", answerTheOrder);
//            return null;
//        }
//
//        int currentFloor = buf.readByte();
//
//        int status2 = buf.readByte();
//        LiftOperatorStatus operatorStatus = getLiftOperatorStatus(status2);
//
//        byte status3 = buf.readByte();
//        int running = status3 & LiftStatusMask.mask0;
//        int downward = (status3 >>> 1) & LiftStatusMask.mask0;
//        int upward = (status3 >>> 2) & LiftStatusMask.mask0;
//        int inTheDoorArea = (status3 >>> 3) & LiftStatusMask.mask0;
//        int throwOver = (status3 >>> 4) & LiftStatusMask.mask0;
//        int fullyLoaded = (status3 >>> 5) & LiftStatusMask.mask0;
//        int openTheDoor = (status3 >>> 6) & LiftStatusMask.mask0;
//        int liftFault = (status3 >>> 7) & LiftStatusMask.mask0;
//
//        byte status4 = buf.readByte();
//        int inService = (status4 >>> 1) & LiftStatusMask.mask0;
//        int openTheDoorInPlace = (status4 >>> 3) & LiftStatusMask.mask0;
//        int emergencyStop = (status4 >>> 4) & LiftStatusMask.mask0;
//        int overload = (status4 >>> 5) & LiftStatusMask.mask0;
//        int closeTheDoor = (status4 >>> 6) & LiftStatusMask.mask0;
//        int closeTheDoorInPlace = (status4 >>> 7) & LiftStatusMask.mask0;
//
//        return new LiftStatusVo(
//                currentFloor,
//                operatorStatus,
//                running,
//                downward,
//                upward,
//                inTheDoorArea,
//                throwOver,
//                fullyLoaded,
//                openTheDoor,
//                liftFault,
//                inService,
//                openTheDoorInPlace,
//                emergencyStop,
//                overload,
//                closeTheDoor,
//                closeTheDoorInPlace
//        );
//    }
//
//    private static LiftOperatorStatus getLiftOperatorStatus(int status2) {
//        LiftOperatorStatus operatorStatus;
//        switch (status2) {
//            case 0x00:
//                operatorStatus = LiftOperatorStatus.Stop;
//                break;
//            case 0x01:
//                operatorStatus = LiftOperatorStatus.Overhaul;
//                break;
//            case 0x02:
//                operatorStatus = LiftOperatorStatus.Firefighting;
//                break;
//            case 0x03:
//                operatorStatus = LiftOperatorStatus.Driver;
//                break;
//            case 0x04:
//                operatorStatus = LiftOperatorStatus.Automatic;
//                break;
//            case 0x05:
//                operatorStatus = LiftOperatorStatus.Special;
//                break;
//            case 0x06:
//            default:
//                operatorStatus = LiftOperatorStatus.Emergency;
//                break;
//        }
//        return operatorStatus;
//    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        liftLog.error("接收错误：", cause);
        super.exceptionCaught(ctx, cause);
    }
}
